package com.tanhua.gateway.filters;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 1、实现GloableFilter接口和Ordered接口
 * 2、实现filter方法和getOrderd方法
 */
@Component
@RefreshScope //配置实时刷新
public class AuthFilter implements GlobalFilter, Ordered {

    //不需要鉴权的url集合
    @Value("${gateway.excludedUrls}")
    private List<String> excludeUrls;  //自动将字符串以“，”分割为数组

    //鉴权过滤器

    /**
     * 需求：
     *  1、针对某些URL地址不需要鉴权
     *  2、如果验证失败，返回401状态，同时相应数据（用户未登录）
     *  3、如果验证成功，向后执行
     */
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest(); //请求对象
        //1、获取当前请求连接的URL地址
        String path = request.getURI().getPath();   //   /user/login

        System.out.println("path = "+ path);
        //2、判断，如果不需要鉴权，向后执行（放行）
        if(excludeUrls.contains(path)) {
            //集合中包含某项数据
            return chain.filter(exchange);
        }
        //3、获取token，并处理
        String token = request.getHeaders().getFirst("Authorization");
        //针对浏览器传递的特殊token，进行处理（Bearer ）
        if(!StringUtils.isEmpty(token)) {
            token = token.replaceAll("Bearer ","");
        }
        //4、使用JWT工具类，验证token是否有效
        boolean verifyToken = JwtUtils.verifyToken(token);
        //5、如果token有效，向后执行（放行）
        if(verifyToken) {
            return chain.filter(exchange);
        }else {
            //6、如果token失效，构造返回，并指定相应状态401
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //return response.setComplete();
            //相应数据
            response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
            //返回的错误数据   {errCode：401，message：xxxx}
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("errCode", 401);
            responseData.put("errMessage", "用户未登录");
            //将对象，转化为json字符串（已byte数组的形式提现）
            byte[] data = JSON.toJSONBytes(responseData);
            DataBuffer buffer = response.bufferFactory().wrap(data); //数据DatBuffer
            return response.writeWith(Mono.just(buffer));
        }
    }

    /**
     * 过滤器：程序员自定义的，内置的
     *
     * @return
     */
    //返回值越大，优先级越低（过滤器的优先级）
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
